package com.duowan.cms.parser.util;

import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;

import com.duowan.cms.common.exception.BaseCheckedException;
import com.duowan.cms.dto.article.ArticleInfo;

/**
 * 模板工厂类
 * 
 * @author Administrator
 */
public class VMFactory {

    //异常码：模板解析失败
    public final static String PARSER_IS_FAIL = VMFactory.class.getName().concat("001");
    public final static String SET_TEMPLATE_IS_FAIL = VMFactory.class.getName().concat("002");
    public final static String SET_TEMPLATE_CONTENT_IS_FAIL = VMFactory.class.getName().concat("003");
    
    private final static Log logger = LogFactory.getLog(VMFactory.class);
    private static VelocityEngine engine = null;

    private String templatebody = null;
    private Map<String, Object> templateData = null;
    Template tpl = null;
    private VelocityContext context = null;

    static {
        engine = new VelocityEngine();
        try {
            engine.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogChute");
            engine.init();
        } catch (Exception e) {
            logger.error("VMFactory 初始化失败", e);
        }
    }

    public VMFactory() {
        context = new VelocityContext();
    }
    
    public VMFactory(String templatebody, Map<String, Object> templateData ) throws BaseCheckedException {
        context = new VelocityContext();
        this.setTemplateBody(templatebody);
        this.setTemplateDate(templateData);
    }

    // 设定模板
    public void setTemplate(String templatefile) throws BaseCheckedException {
        try {
            tpl = engine.getTemplate(templatefile, "GBK");
        } catch (Exception e) {
            logger.error("setTemplate error ,templatefile=" + templatefile, e);
            throw new BaseCheckedException(SET_TEMPLATE_IS_FAIL, "设置模板templatefile="+templatefile+"失败");
        }
        this.templatebody = null;
    }

    // 设定模板内容
    public void setTemplateBody(String templatebody) throws BaseCheckedException {
        try {
            this.templatebody = templatebody;
            this.tpl = null;
        } catch (Exception e) {
            logger.error("setTemplateBody error,templatebody=" + templatebody, e);
            throw new BaseCheckedException(SET_TEMPLATE_CONTENT_IS_FAIL, "设置模板内容templatebody="+templatebody+"失败");
        }
    }

    // 填充数据
    public void setTemplateDate(Map<String, Object> data) {
        this.templateData = data;
    }

    /**
     * 获取解析后的结果
     * @return
     * @throws BaseCheckedException
     */
    public String getResultString() throws BaseCheckedException {
        StringWriter out = new StringWriter();
        try {
            output(out);
            return out.toString();
        } catch (Exception e) {
            logger.error("模板解析出错("+this.templateData.get("parseringObjectId")+")，原因："+e);
            throw new BaseCheckedException(PARSER_IS_FAIL, "模板解析出错("+this.templateData.get("parseringObjectId")+")，原因："+e);
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                logger.error("out.close error:", e);
            }
        }
    }

    // 输出到流
    private void output(Writer out) {
        // 创建上下文，填充数据
        for(String key : this.templateData.keySet()) {
            context.put(key, templateData.get(key));
        }
        // 这样做的目的是可以使用嵌套的模板语句
        if (this.tpl != null) {
            // 获得一个模板，把模板和数据合并，输出到Writer
            tpl.merge(context, out);
        } else {
            // 直接使用templatebody合并
            engine.evaluate(context, out, "", templatebody);
        }
    }
    
    public static void main(String[] args) {
        VelocityEngine engine = new VelocityEngine(); 
        //engine.init(); 
        // 取得velocity的模版          
        Properties p =new Properties();  
        p.put(Velocity.FILE_RESOURCE_LOADER_PATH, "G:\\svn_source\\cmsfabu\\cms-parent\\cms-parser\\cms-parser-service\\target\\classes");  
        engine.init(p);  
        Template template = engine.getTemplate( "com\\duowan\\cms\\parser\\util\\example.vm" ); 
        VelocityContext context = new VelocityContext(); 
        StringWriter writer = new StringWriter(); 
        template.merge( context, writer ); 
        System.out.println( writer.toString() +"==");
    }
    
}
